﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using ChoWorkflowServer.Model;
using System.Windows.Interop;
using System.Data;
using Cinchoo.Core;
using Cinchoo.Core.WPF;
using Cinchoo.Core.Windows.Forms;

namespace ChoWorkflowDashboard
{
    /// <summary>
    /// Interaction logic for AddOrEditRolesWindow.xaml
    /// </summary>
    public partial class AddOrEditRolesWindow : ChoBaseWindowEx
    {
        private readonly IChoDataModel _dataModel = ChoDataModelFactory.New();

        private bool _isDataUpdated;
        internal bool IsDataUpdated
        {
            get { return _isDataUpdated; }
            set
            {
                if (value)
                    _isDataUpdated = value;
            }
        }

        public ChoTasksDataSet.CHO_ROLESDataTable RolesTable
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_ROLE_USERSDataTable UserRolesTable
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_ROLE_POLICYDataTable RolePolicyTable
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_USERSDataTable UsersTable
        {
            get;
            set;
        }

        public ChoTasksDataSet.CHO_POLICYDataTable PolicyTable
        {
            get;
            set;
        }

        public AddOrEditRolesWindow()
        {
            using (new ChoWaitCursor())
            {
                RolesTable = _dataModel.GetAllRoles();
                UsersTable = _dataModel.GetAllUsers();
                PolicyTable = _dataModel.GetAllPolicy();

                //Add expression columns
                UsersTable.Columns.Add("DISPLAY_NAME", typeof(String), @"FULL_NAME + ' [' + NAME + ']'");

                InitializeComponent();
                this.DataContext = this;
            }
        }

        private void btnNewRole_Click(object sender, RoutedEventArgs e)
        {
            if (txtRoleName.Text.Trim().Length == 0) return;
            
            var x = (from row1 in RolesTable.AsEnumerable<ChoTasksDataSet.CHO_ROLESRow>()
                     where row1[RolesTable.NAMEColumn, DataRowVersion.Original] != DBNull.Value
                    && (string)row1[RolesTable.NAMEColumn, DataRowVersion.Original] == txtRoleName.Text
                     select row1).FirstOrDefault();
            if (x != null) return;

            ChoTasksDataSet.CHO_ROLESRow row = RolesTable.NewCHO_ROLESRow();
            row.NAME = txtRoleName.Text.Trim();
            row.COMMENT = String.Empty;
            row.ENABLED = true;
            RolesTable.AddCHO_ROLESRow(row);

            txtRoleName.Text = String.Empty;
            lstRoles.SelectedIndex = lstRoles.Items.Count - 1;
            e.Handled = true;
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            _promptSaveChanges = false;
            DialogResult = true;
            //this.Close();
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
        }

        private void AcceptChanges()
        {
            RolesTable.AcceptChanges();
            UserRolesTable.AcceptChanges();
            RolePolicyTable.AcceptChanges();
        }

        protected override void RejectChanges()
        {
            RolesTable.RejectChanges();
            UserRolesTable.RejectChanges();
            RolePolicyTable.RejectChanges();
        }

        private void btnUserAdd_Click(object sender, RoutedEventArgs e)
        {
            if (lstAvailUsers.SelectedItem == null
                || lstRoles.SelectedItem == null)
                return;

            ChoTasksDataSet.CHO_USERSRow userRow = ((DataRowView)lstAvailUsers.SelectedItem).Row as ChoTasksDataSet.CHO_USERSRow;
            ChoTasksDataSet.CHO_ROLESRow roleRow = ((DataRowView)lstRoles.SelectedItem).Row as ChoTasksDataSet.CHO_ROLESRow;

            ChoTasksDataSet.CHO_ROLE_USERSRow x = null;
            foreach (ChoTasksDataSet.CHO_ROLE_USERSRow row1 in UserRolesTable.AsEnumerable())
            {
                if (row1.RowState == DataRowState.Deleted
                    && (int)row1[UserRolesTable.USER_IDColumn, DataRowVersion.Original] == userRow.ID)
                {
                    x = row1;
                    x.RejectChanges();
                    break;
                }
                else if (row1.RowState != DataRowState.Deleted && (int)row1[UserRolesTable.USER_IDColumn] == userRow.ID)
                {
                    x = row1;
                    break;
                }
            }

            if (x != null) return;

            ChoTasksDataSet.CHO_ROLE_USERSRow row = UserRolesTable.NewCHO_ROLE_USERSRow();
            row.ID = roleRow.ID;
            row.NAME = roleRow.NAME;
            row.USER_ID = userRow.ID;
            row.USER_NAME = userRow.NAME;
            row.USER_FULL_NAME = userRow.FULL_NAME;

            UserRolesTable.AddCHO_ROLE_USERSRow(row);

            e.Handled = true;
        }

        private void btnUserRemove_Click(object sender, RoutedEventArgs e)
        {
            if (lstSelectedUsers.SelectedItem == null)
                return;

            ChoTasksDataSet.CHO_ROLE_USERSRow userRoleRow = ((DataRowView)lstSelectedUsers.SelectedItem).Row as ChoTasksDataSet.CHO_ROLE_USERSRow;
            userRoleRow.Delete();
            e.Handled = true;

        }

        private void btnPolicyAdd_Click(object sender, RoutedEventArgs e)
        {
            if (lstAvailPolicy.SelectedItem == null
                || lstRoles.SelectedItem == null)
                return;

            ChoTasksDataSet.CHO_POLICYRow policyRow = ((DataRowView)lstAvailPolicy.SelectedItem).Row as ChoTasksDataSet.CHO_POLICYRow;
            ChoTasksDataSet.CHO_ROLESRow roleRow = ((DataRowView)lstRoles.SelectedItem).Row as ChoTasksDataSet.CHO_ROLESRow;

            ChoTasksDataSet.CHO_ROLE_POLICYRow x = null;
            foreach (ChoTasksDataSet.CHO_ROLE_POLICYRow row1 in RolePolicyTable.AsEnumerable())
            {
                if (row1.RowState == DataRowState.Deleted
                    && (int)row1[RolePolicyTable.POLICY_IDColumn, DataRowVersion.Original] == policyRow.POLICY_ID)
                {
                    x = row1;
                    x.RejectChanges();
                    break;
                }
                else if (row1.RowState != DataRowState.Deleted && (int)row1[RolePolicyTable.POLICY_IDColumn] == policyRow.POLICY_ID)
                {
                    x = row1;
                    break;
                }
            }

            if (x != null) return;

            ChoTasksDataSet.CHO_ROLE_POLICYRow row = RolePolicyTable.NewCHO_ROLE_POLICYRow();
            row.ID = roleRow.ID;
            row.NAME = roleRow.NAME;
            row.POLICY_ID = policyRow.POLICY_ID;
            row.POLICY_DESC = policyRow.POLICY_DESC;

            RolePolicyTable.AddCHO_ROLE_POLICYRow(row);

            e.Handled = true;
        }

        private void btnPolicyRemove_Click(object sender, RoutedEventArgs e)
        {
            if (lstSelectedPolicy.SelectedItem == null)
                return;

            ChoTasksDataSet.CHO_ROLE_POLICYRow row = ((DataRowView)lstSelectedPolicy.SelectedItem).Row as ChoTasksDataSet.CHO_ROLE_POLICYRow;
            row.Delete();
            e.Handled = true;
        }

        protected override bool UpdateChanges()
        {
            try
            {
                _dataModel.UpdateRoles(RolesTable.GetChanges() as ChoTasksDataSet.CHO_ROLESDataTable,
                    UserRolesTable.GetChanges() as ChoTasksDataSet.CHO_ROLE_USERSDataTable,
                    RolePolicyTable.GetChanges() as ChoTasksDataSet.CHO_ROLE_POLICYDataTable, ChoUser.CurrentUser, Environment.MachineName);

                AcceptChanges();
                
                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error while updating roles.{0}{1}.".FormatString(Environment.NewLine, ex.Message),
                    Application.Current.MainWindow.Title, MessageBoxButton.OK, MessageBoxImage.Error);

                return false;
            }
        }

        protected override bool HasChanges
        {
            get
            {
                DataTable table = null;
                bool hasChanges = false;

                if (!hasChanges)
                {
                    table = RolesTable != null ? RolesTable.GetChanges() : null;
                    if (table != null && table.Rows.Count > 0)
                        hasChanges = true;
                }
                if (!hasChanges)
                {
                    table = UserRolesTable != null ? UserRolesTable.GetChanges() : null;
                    if (table != null && table.Rows.Count > 0)
                        hasChanges = true;
                }
                if (!hasChanges)
                {
                    table = RolePolicyTable != null ? RolePolicyTable.GetChanges() : null;
                    if (table != null && table.Rows.Count > 0)
                        hasChanges = true;
                }

                IsDataUpdated = hasChanges;
                return hasChanges;
            }
        }

        private void lstRoles_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (lstRoles.SelectedItem == null)
                return;

            if (HasChanges)
            {
                if (!UpdateChanges())
                    RejectChanges();

            }
            ChoTasksDataSet.CHO_ROLESRow row = ((DataRowView)lstRoles.SelectedItem).Row as ChoTasksDataSet.CHO_ROLESRow;

            RolePolicyTable = _dataModel.GetAllRolePolicy(row.ID);
            UserRolesTable = _dataModel.GetAllUserRoles(row.ID);

            //Add expression columns
            UserRolesTable.Columns.Add("USER_DISPLAY_NAME", typeof(String), @"USER_FULL_NAME + ' [' + USER_NAME + ']'");

            BindingOperations.GetBindingExpression(lstSelectedUsers, ListBox.ItemsSourceProperty).UpdateTarget();
            BindingOperations.GetBindingExpression(lstSelectedPolicy, ListBox.ItemsSourceProperty).UpdateTarget();

        }

        private void btnDeleteRole_Click(object sender, RoutedEventArgs e)
        {
            object selectedItem = lstRoles.SelectedItem;
            if (selectedItem == null) return;
            ChoTasksDataSet.CHO_ROLESRow row = ((DataRowView)selectedItem).Row as ChoTasksDataSet.CHO_ROLESRow;
            if (row == null) return;

            if (MessageBox.Show("Are you sure you want to delete the '{0}' role?".FormatString(row.NAME), Application.Current.MainWindow.Title,
                MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
                return;

            row.Delete();
            e.Handled = true;
        }

        private void lstSelectedUsers_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            btnUserRemove_Click(sender, e);
        }

        private void lstSelectedPolicy_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            btnPolicyRemove_Click(sender, e);
        }

        private void txtComments_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            ChoMultilineInputWindow multilineInputWindow = new ChoMultilineInputWindow(txtComments.Text, "Please enter role comments");
            ChildWindow = multilineInputWindow;
            bool? retValue = multilineInputWindow.ShowDialog();
            if (retValue == null || !retValue.Value)
                return;

            txtComments.Text = multilineInputWindow.InputText;
            //BindingOperations.GetBindingExpression(txtComments, TextBox.TextProperty).UpdateSource();
        }

        private void lstRoles_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //txtComments_MouseDoubleClick(sender, e);
        }
    }
}
